xarray time series
Offifial examples
Examples
Montly mean
code:python
monthly_avg = ds.resample(time="1MS").mean()
daily anomaly
code:python
if not 'dayofyear' in da.coords:
da.coords'dayofyear'=xr.where((da.dayofyear>59) & (~da.time.dt.is_leap_year),da.dayofyear+1,da.dayofyear) da_clim=da.groupby('dayofyear').mean()
da_clim=da_climda_clim.dayofyear!=60.interp(dayofyear=range(1,367)) # Feb 29 is the mean of Feb 28 and Mar 1 da_anomaly=da.groupby("dayofyear")-da_clim
By monthly mean from daily data
code:python
# in python 3 , "/2" should be "//2"
def bimonthly_mean(ds, calendar='standard'):
labels=xr.DataArray((ds.time.to_index().month+1)/2,coords=[ds"time"],name="labels") bimonthly=ds.groupby(labels).mean("time")
return bimonthly
Calculating Seasonal long-time Averages (JFM, AMJ, JAS, OND) from Timeseries of Monthly Means
code:python
# define season
# in python 3, "/3" should be "//3"
season=xr.DataArray([seasonnameint(n) for n in (ds.time.to_index().month-1)/3],coords=[ds"time"],name="season") #for "MAM","JJA","SOD","DJF" ## season=xr.DataArray([seasonnameint(n) for n in (ds.time.to_index().month-3)//3],coords=[ds"time"],name="season") ##
month_length = ds.time.dt.days_in_month
#
# Calculate the weights by grouping by 'season'.
# Conversion to float type ('astype(float)') only necessary for Python 2.x
weights = month_length.groupby(season) / month_length.astype(float).groupby(season).sum()
# check of weights
weights.groupby(season).sum()
# calculate weighted mean
dsweighted=(ds*weights).groupby(season).sum(dim="time")
time series of each season from monthly values (share similar parts with above example)
code:python
df_season=df.where(season==cseason,drop=True)
year=xr.DataArray(df_season.time.to_index().year,coords=[df_season"time"],name="year") month_length_season=month_length.where(season==cseason,drop=True)
weights = month_length_season.groupby(year) / month_length_season.groupby(year).sum()
df_season_mean=(df_season*weights).groupby(year).sum("time")
Speed up time aggregation by normalizing the time coordinate before resample / groupby_bins
Irregular timestamps, duplicate times, mixed calendars, or slight time jitter can make time operations heavier than necessary. A quick “time normalization” step can reduce task overhead.
code:python
# Example: floor timestamps to daily, sort, and drop duplicates before daily means
ds2 = ds.assign_coords(time=t).sortby("time")
ds2 = ds2.sel(time=~ds2.get_index("time").duplicated())
daily = ds2"sst".resample(time="1D").mean() If you repeatedly use daily/weekly/monthly products downstream, writing them once (e.g., to Zarr) often pays off.
add time dimension to 2d dataset
code:pyhton
import datetime as dt
td=dt.datetime(2019,1,1)
dataset.expand_dims(dim={"time":td}) shift time
code:python
U_shifted=U.copy()
Event-centered composites (e.g., marine heatwaves) using a “relative-time” axis
code:python
tau = 7
segs = []
for t0 in event_times:
seg = ds"sst".sel(time=slice(t0 - np.timedelta64(tau, "D"), t0 + np.timedelta64(tau, "D")))
seg = seg.assign_coords(rel_day=(seg.time - t0) / np.timedelta64(1, "D")).swap_dims({"time": "rel_day"})
segs.append(seg)
comp = xr.concat(segs, dim="event").mean("event")
Why it’s useful: captures canonical pre/post-event evolution that monthly means often miss.
Event-based compositing (marine heatwaves, eddies)
Define events as boolean masks and use them to build composites without explicit loops.
code:python
# Example: threshold-based events
# Composite SSH during events
comp = ds"zos".where(mhw).mean("time") Extension: label connected events (via scipy.ndimage) and compute per-event statistics lazily.
Tips